#include <algorithm>
#include <cstdio>

const int N = 50005, M = 100005, inf = 0x3fffffff;
int n, m, ans = inf, f[N + M], val[N + M];

struct Edge {
  int x, y, a, b;
  inline bool operator<(const Edge &rhs) const { return a < rhs.a; }
} e[M];

struct Node {
  int fa, ch[2], id;
  bool rev;
} tr[N + M];

int find(int x) { return f[x] == x ? x : f[x] = find(f[x]); }

inline bool iden(const int &x) { return tr[tr[x].fa].ch[1] == x; }

inline bool isnrt(const int &x) {
  return tr[tr[x].fa].ch[0] == x || tr[tr[x].fa].ch[1] == x;
}

inline void pushup(const int &x) {
  static int ls, rs;
  ls = tr[x].ch[0], rs = tr[x].ch[1];
  tr[x].id = x;
  if (ls && val[tr[ls].id] > val[tr[x].id]) tr[x].id = tr[ls].id;
  if (rs && val[tr[rs].id] > val[tr[x].id]) tr[x].id = tr[rs].id;
}

inline void reverse(const int &x) {
  static int tmp;
  tmp = tr[x].ch[0];
  tr[x].ch[0] = tr[x].ch[1];
  tr[x].ch[1] = tmp;
  tr[x].rev ^= 1;
}

inline void pushdown(const int &x) {
  if (tr[x].rev) {
    if (tr[x].ch[0]) reverse(tr[x].ch[0]);
    if (tr[x].ch[1]) reverse(tr[x].ch[1]);
    tr[x].rev = false;
  }
}

inline void pushall(const int &x) {
  if (isnrt(x)) pushall(tr[x].fa);
  pushdown(x);
}

inline void rotate(const int &x) {
  bool xtofa = iden(x);
  int fa = tr[x].fa, ffa = tr[fa].fa, son = tr[x].ch[!xtofa];
  if (isnrt(fa)) tr[ffa].ch[iden(fa)] = x;
  tr[x].fa = ffa;
  tr[x].ch[!xtofa] = fa;
  tr[fa].ch[xtofa] = son;
  if (son) tr[son].fa = fa;
  tr[fa].fa = x;
  pushup(fa);
}

inline void splay(const int &x) {
  pushall(x);
  for (int fa; isnrt(x); rotate(x))
    if (isnrt(fa = tr[x].fa)) rotate(iden(fa) == iden(x) ? fa : x);
  pushup(x);
}

inline void access(int x) {
  for (int y = 0; x; y = x, x = tr[x].fa) splay(x), tr[x].ch[1] = y, pushup(x);
}

inline void makert(const int &x) { access(x), splay(x), reverse(x); }

inline int findrt(int x) {
  access(x), splay(x);
  while (tr[x].ch[0]) pushdown(x), x = tr[x].ch[0];
  splay(x);
  return x;
}

inline void link(int x, int y) { makert(x), tr[x].fa = y; }

inline void cut(int x, int y) {
  makert(x), access(y), splay(y);
  tr[y].ch[0] = tr[x].fa = 0;
  pushup(y);
}

inline int query(int x, int y) { return makert(x), access(y), splay(y), tr[y].id; }

int main() {
#ifndef ONLINE_JUDGE
#ifdef LOCAL
  freopen("testdata.in", "r", stdin);
  freopen("testdata.out", "w", stdout);
#else
  freopen("P2387 [NOI2014]魔法森林.in", "r", stdin);
  freopen("P2387 [NOI2014]魔法森林.out", "w", stdout);
#endif
#endif

  scanf("%d%d", &n, &m);
  for (int i = 1; i <= m; ++i) { scanf("%d%d%d%d", &e[i].x, &e[i].y, &e[i].a, &e[i].b); }
  std::sort(e + 1, e + m + 1);
  for (int i = 1; i <= n + m; ++i) f[i] = tr[i].id = i;
  for (int i = n + 1; i <= n + m; ++i) val[i] = e[i - n].b;
  for (int i = 1, u, v, tmp; i <= m; ++i) {
    if (find(u = e[i].x) == find(v = e[i].y)) {
      tmp = query(u, v);
      if (val[tmp] > e[i].b) {
        cut(e[tmp - n].x, tmp), cut(tmp, e[tmp - n].y);
        link(u, i + n), link(i + n, v);
      }
    } else {
      link(i + n, v), link(u, i + n);
      f[find(u)] = find(v);
    }
    if (find(1) == find(n)) { ans = std::min(ans, e[i].a + val[query(1, n)]); }
  }
  if (ans == inf) puts("-1");
  else
    printf("%d", ans);
  return 0;
}